import 'package:aero_frisbee/app/model/af_block_list_model/af_block_list_model.dart';
import 'package:aero_frisbee/app/req/af_req_api.dart';
import 'package:aero_frisbee/app/state/easy_refresh_state.dart';
import 'package:aero_frisbee/core/state/view_state.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import 'af_followed_list_state.dart';

part 'af_followed_list_view_model.g.dart';

@riverpod
class AddFriendService extends _$AddFriendService {
  @override
  ViewState<bool> build() {
    return const ViewState.idle();
  }

  addFriend({required String userId}) async {
    final api = ref.watch(appApiProvider);
    state = const ViewState.loading();
    try {
      final model = await api.addFriend(userId: userId);
      state = ViewState.ready(model);
    } catch (e) {
      state = ViewState.error(error: e.toString());
    }
  }
}

@riverpod
class UnfriendService extends _$UnfriendService {
  @override
  ViewState<bool> build() {
    return const ViewState.idle();
  }

  unfriend({required String userId}) async {
    final api = ref.watch(appApiProvider);
    state = const ViewState.loading();
    try {
      final model = await api.unfriend(userId: userId);
      state = ViewState.ready(model);
    } catch (e) {
      state = ViewState.error(error: e.toString());
    }
  }
}

@riverpod
class ReportService extends _$ReportService {
  @override
  ViewState<bool> build() {
    return const ViewState.idle();
  }

  report({required String userId, required String complainSub}) async {
    final api = ref.watch(appApiProvider);
    state = const ViewState.loading();
    try {
      final model = await api.report(userId: userId, complainSub: complainSub);
      state = ViewState.ready(model);
    } catch (e) {
      state = ViewState.error(error: e.toString());
    }
  }
}

const pageSize = 20;

@riverpod
class AfFollowedListService extends _$AfFollowedListService {
  @override
  FutureOr<AfFollowedListState> build() {
    final api = ref.read(appApiProvider);
    return api.getFriendsList(page: 1, limit: pageSize);
  }

  AfFollowedListState? get _curState =>
      state.maybeWhen(orElse: () => null, data: (data) => data);

  refresh() async {
    if (_curState != null) {
      try {
        _updateRefreshing();
        final api = ref.read(appApiProvider);
        final ret = await api.getFriendsList(
            page: _curState?.currentPage ?? 1, limit: pageSize);
        state = AsyncData(ret);
      } catch (e) {
        state = AsyncData(_curState!.copyWith(
            refreshState: EasyRefreshState.refreshErr(error: e.toString())));
      }
    }
  }

  loadMore() async {
    if (_curState != null) {
      try {
        _updateLoadMore();
        final api = ref.read(appApiProvider);
        final ret = await api.getFriendsList(
            page: _curState?.currentPage ?? 1, limit: pageSize);
        state = AsyncData(ret.copyWith(
            refreshState: EasyRefreshState.loadMoreSuccess(
                hasMore: ret.dataList.length >= pageSize),
            dataList: [..._curState!.dataList, ...ret.dataList]));
      } catch (e) {
        state = AsyncData(_curState!.copyWith(
            refreshState: EasyRefreshState.loadMoreErr(error: e.toString())));
      }
    }
  }

  _updateRefreshing() {
    if (_curState != null) {
      state = AsyncData(_curState!.copyWith(
          refreshState: const EasyRefreshState.refreshStart(), currentPage: 1));
    }
  }

  _updateLoadMore() {
    if (_curState != null) {
      state = AsyncData(_curState!
          .copyWith(refreshState: const EasyRefreshState.loadMoreStart()));
    }
  }
}

@riverpod
class UnblockService extends _$UnblockService {
  @override
  ViewState<bool> build() {
    return const ViewState.idle();
  }

  unblock({required String broadcasterId}) async {
    final api = ref.watch(appApiProvider);
    state = const ViewState.loading();
    try {
      final model = await api.unblock(broadcasterId: broadcasterId);
      state = ViewState.ready(model);
    } catch (e) {
      state = ViewState.error(error: e.toString());
    }
  }
}

@riverpod
class BlockService extends _$BlockService {
  @override
  ViewState<bool> build() {
    return const ViewState.idle();
  }

  block({required String broadcasterId}) async {
    final api = ref.watch(appApiProvider);
    state = const ViewState.loading();
    try {
      final model = await api.block(broadcasterId: broadcasterId);
      state = ViewState.ready(model);
    } catch (e) {
      state = ViewState.error(error: e.toString());
    }
  }
}

@riverpod
FutureOr<List<AfBlockListModel>> getBlockListFuture(
  GetBlockListFutureRef ref,
) {
  final api = ref.watch(appApiProvider);
  return api.getBlockList();
}
